=begin

This file is part of the RSIF project, http://rsif.googlecode.com

Copyright (c) 2009-2009 Roberto Dario Seminara <robertodarioseminara@gmail.com>

rsif is free software: you can redistribute it and/or modify
it under the terms of the gnu general public license as published by
the free software foundation, either version 3 of the license, or
(at your option) any later version.

rsif is distributed in the hope that it will be useful,
but without any warranty; without even the implied warranty of
merchantability or fitness for a particular purpose.  see the
gnu general public license for more details.

you should have received a copy of the gnu general public license
along with rsif.  if not, see <http://www.gnu.org/licenses/>.
=end

module Rsif
module Core
module Classes

require "classes/roleclass"
require "logger/contextlogger"

module ProbeFactory
    # un ProbeFactory es un RoleClass, solo que agrega la capacidad 
    # de crear objetos probando todas las subclases
    include RoleClass
    include Rsif::Core::Logging

	class << self
    		include Rsif::Core::Logging
	end

    # mediante el modulo FactoryMethods, se definen los metodos que se incluyen
    # en las clases que incluyen el modulo ProbeFactory
    module FactoryMethods

	include Rsif::Core::Logging
      # ahora el metodo create no devuelve una nueva instancia de self
      # en lugar de eso, itera en todas sus subclasses, buscando alguna
      # que pueda instanciar y que ademas el objeto funcione
      # FIXME: enviar esta logica de verificacion de instanciacion + creacion + verificacion del objeto
      # a otro lugar. Encapsularla bien

      def create( params = nil)
	subclasses.each do |clas|
	  begin
	    if (self.can_instantiate_class(clas) )
	      logger.debug "can instantiate #{clas}\n"

		begin
	      	obj = clas.create(params) 
		rescue
		obj = clas.create
		end
	      return obj if obj.good
	    end
	  rescue Exception => e
		logger.warn "#{e} al intentar instanciar #{clas}\n"
	  end
	end

	raise "Not available object"
      end

      def can_instantiate_class(clas)
	begin
	    c = clas.can_instantiate
	    return c
	rescue Exception => e
	  logger.error "Exception #{e} class #{clas}\n"
	end
	return nil
      end

    end

    # debe invocarse self.included de RoleClass para asegurarse
    # de que se registre como si hubiera extendido directamente a ese modulo
    def self.included( klass )
      logger.log -6, "#{klass} extended\n"
      klass.extend FactoryMethods
      RoleClass.included( klass )
    end
    
end

end
end
end

